package cn.piggy.gateway.sdk.application;

import cn.piggy.gateway.sdk.exception.GatewayException;
import cn.piggy.gateway.sdk.annotation.ApiProducerClazz;
import cn.piggy.gateway.sdk.annotation.ApiProducerMethod;
import cn.piggy.gateway.sdk.config.GatewaySDKServiceProperties;
import cn.piggy.gateway.sdk.domain.service.GatewayCenterService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.curator.framework.CuratorFramework;
import org.apache.zookeeper.CreateMode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.List;

@Component
public class GatewaySDKApplication implements BeanPostProcessor, InitializingBean {

    private final Logger logger = LoggerFactory.getLogger(GatewaySDKApplication.class);

    @Resource
    private GatewaySDKServiceProperties properties;
    @Resource
    private GatewayCenterService gatewayCenterService;
    @Resource
    private CuratorFramework curatorFramework;

    public GatewaySDKApplication() {}

    // queryGatewayId
    @Override
    public void afterPropertiesSet() {
        // 查询 gatewayId
        List<String> gatewayIds = gatewayCenterService.queryGatewayId(properties.getInterfaceAddress(),properties.getSystemId());
        for(String gatewayId : gatewayIds){
            new Thread(() -> {
                try {
                    curatorFramework.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL_SEQUENTIAL)
                            .forPath("/"+gatewayId+"/"+properties.getSystemId()+"/node", properties.getSystemAddress().getBytes());
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }).start();
        }

        gatewayCenterService.doRegisterApplication(properties.getInterfaceAddress(), properties.getSystemId(),
                properties.getSystemName(), properties.getType(),
                properties.getSystemRegistry(), properties.getSystemAddress());
        logger.info("send ---> application ---> register");
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, @NonNull String beanName) throws BeansException {
        ApiProducerClazz apiProducerClazz = bean.getClass().getAnnotation(ApiProducerClazz.class);
        if (null == apiProducerClazz)
            return bean;

        String interfaceId;
        String interUri = apiProducerClazz.uri();
        // 2. 接口信息
        Class<?>[] interfaces = bean.getClass().getInterfaces();
        if (interfaces.length == 0) {
            interfaceId = bean.getClass().getName();
        }else if (interfaces.length == 1){
            interfaceId = interfaces[0].getName();
        }else{
            throw new GatewayException(bean.getClass().getName() + "interface number > 1 this is " + JSON.toJSONString(interfaces));
        }

        gatewayCenterService.doRegisterApplicationInterface(properties.getInterfaceAddress(),
                properties.getSystemId(),
                interfaceId,
                apiProducerClazz.interfaceName(),
                apiProducerClazz.interfaceVersion());

        List<JSONObject> jsonObjectList = new ArrayList<>();
        // 3. 方法信息
        Method[] methods = bean.getClass().getMethods();
        for (Method method : methods) {
            ApiProducerMethod apiProducerMethod = method.getAnnotation(ApiProducerMethod.class);
            if (apiProducerMethod == null)
                continue;
            // 解析参数
            Parameter[] allParameters = method.getParameters();
            String parameterType = "";
            String parameterName = "";
            if(allParameters.length!=0){
                StringBuilder pt = new StringBuilder();
                StringBuilder pn = new StringBuilder();
                for(Parameter p : allParameters){
                    Class<?> type = p.getType();
                    String name = p.getName();
                    pt.append(type.getName()).append(",");
                    pn.append(name).append(",");
                }
                parameterType = pt.substring(0, pt.toString().lastIndexOf(","));
                parameterName = pn.substring(0, pn.toString().lastIndexOf(","));
            }
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("systemId",properties.getSystemId());
            jsonObject.put("interfaceId",interfaceId);
            jsonObject.put("methodId",method.getName());
            jsonObject.put("methodType",apiProducerMethod.methodType());
            jsonObject.put("parameterType",parameterType);
            jsonObject.put("parameterName",parameterName);
            jsonObject.put("uri",interUri + apiProducerMethod.uri());
            jsonObject.put("httpCommandType",apiProducerMethod.httpCommandType());
            jsonObject.put("auth",apiProducerMethod.auth());
            jsonObject.put("role",apiProducerMethod.role());
            jsonObjectList.add(jsonObject);
//            gatewayCenterService.doRegisterApplicationInterfaceMethod(properties.getInterfaceAddress(),
//                    properties.getSystemId(),
//                    interfaceId,
//                    method.getName(),
//                    apiProducerMethod.methodType(),
//                    parameterType,
//                    parameterName,
//                    interUri + apiProducerMethod.uri(),
//                    apiProducerMethod.httpCommandType(),
//                    apiProducerMethod.auth(),apiProducerMethod.role());
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("data", jsonObjectList);
        gatewayCenterService.doRegisterApplicationInterfaceMethod(properties.getInterfaceAddress() ,jsonObject);
        return bean;
    }
}
